import re

from django.contrib.auth import login, logout
from django.http import JsonResponse, request, response
from django.shortcuts import render

# Create your views here.
"""
需求分析：根据页面的功能（从上到下，从左到右），哪些功能需要和后端配合完成、
如何确定哪些功能需要和后端进行叫交互
    1.经验
    2.关注类似网站相似功能    
"""
"""
判断用户名是否重复的功能。

前端：  当用户输入用户名之后，失去焦点，发送应该axios（ajax）请求

后端(思路)：
    请求：     接受用户名
    业务逻辑：  根据用户名查询数据库，如果查询数量等于0，说明没用注册
              如果查询结果等于1，说明有注册
    响应：     返回给前端，用户名是否重复
              JSON{code:0,count:0/1,errmsg:ok}
    路由：     GET   /usernames/<username>/count/
    步骤：
    1.接受用户名
    2.根据用户名查询数据库
    3.返回给前端 JSON    
"""

from django.views import View
from apps.users.models import User
from django.http import JsonResponse


class UsernameCountView(View):

    def get(self, request, username):
        # 接受用户名 对用户名进行判断
        # if not re.match('[a-zA-Z0-9_-]{5,20}', username):
        #     return JsonResponse({'code': 200, 'errmsg': '用户名格式错误'})
        # 根据用户名查询数据库
        count = User.objects.filter(username=username).count()
        # 返回给前端
        return JsonResponse({'code': 0,
                             'count': count,
                             'errmsg': 'ok'
                             })


"""
不相信前端提交的数据！！
前端：当用户输入用户名，密码，确认密码，手机号，是否同意协议之后，会点击注册按钮
     前端会发生axios请求

后端：
    请求：        接受请求，获取数据
    业务逻辑：     验证数据，数据入库
    响应：        JSON{code:0,errmsg:ok}
    路由：         POST   register/
    步骤：
    # 1.接受请求（POST---------JSON）
    # 2.获取数据
    # 3.验证数据
    #     3.1 用户名，密码，确认密码，手机号，是否同意协议都要有
    #     3.2 用户名满足规则，用户名不能重复
    #     3.3 密码满足规则
    #     3.4确认密码和密码一致
    #     3.5 手机号满足规则，手机号不能重复
    #     3.6 是否同意协议
    # 4.数据入库
    # 5.返回响应    
"""
import json


class RegisterView(View):

    def post(self, request):
        # 1.
        # 接受请求（POST - --------JSON）
        body_bytes = request.body
        body_str = body_bytes.decode()
        body_dict = json.loads(body_str)
        # 2.获取数据
        username = body_dict.get('username')
        password = body_dict.get('password')
        password2 = body_dict.get('password2')
        mobile = body_dict.get('mobile')
        allow = body_dict.get('allow')
        sms_code = body_dict.get('sms_code')

        # 3.验证数据
        #     3.1 用户名，密码，确认密码，手机号，是否同意协议都要有
        # all里的元素只要是None,False则返回False否则True
        if not all([username, password, password2, mobile, allow, sms_code]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})
        #     3.2 用户名满足规则，用户名不能重复
        if not re.match('[a-zA-Z_-]{5,20}', username):
            return JsonResponse({'code': 400, 'errmsg': '用户名不满足规则'})
        #     3.3 密码满足规则
        if not len(password) >= 8 and len(password) <= 20:
            return JsonResponse({'code': 400, 'errmsg': '密码不满足规则'})
        #     3.4确认密码和密码一致
        if not password == password2:
            return JsonResponse({'code': 400, 'errmsg': '密码不一致'})
        #     3.5 手机号满足规则，手机号不能重复
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400, 'errmsg': 'mobile格式有误!'})
        #     3.6 验证短信验证码是否正确
        #     3.6.1 建立redis连接
        from django_redis import get_redis_connection
        redis_cli = get_redis_connection('code')
        #     3.6.2 获取redis数据
        redis_sms_code = redis_cli.get(mobile).decode()
        #     3.6.3 验证短信验证码是否过期
        if redis_sms_code is None:
            return JsonResponse({'code': 400, 'errmsg': '短信验证码已过期'})
        #     3.6.4 验证短信验证码是否正确
        if not sms_code == redis_sms_code:
            return JsonResponse({'code': 400, 'errmsg': '短信验证码错误'})
        #     3.7 是否同意协议
        if not allow:
            return JsonResponse({'code': 400, 'errmsg': '未同意协议'})
        # 4.数据入库
        # user = User(username=username, password=password, mobile=mobile)
        # user.save()
        # User.objects.create(username=username, password=password, mobile=mobile)
        # 密码没加密 使用以下方式加密
        user = User.objects.create_user(username=username, password=password, mobile=mobile)
        # 设置session
        login(request, user)
        # request.session['id'] = user.id

        # 5.返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok'})


"""
如果需求是注册成功后即表示用户认证通过，那么此时可以在注册成功后实现状态保持
如果需求是注册成功后不表示用户认证通过，那么此时可以在登录成功后实现状态保持
    实现状态保持主要有两种方式：
    1.基于cookie实现状态保持
    2.基于session实现状态保持
"""

"""
登录
    
前端：
        当用户把用户名和密码输入完成之后，会点击登录按钮。这个时候前端应该发送一个axios请求
        
后端：
    请求    ：  接收数据，验证数据
    业务逻辑：   验证用户名和密码是否正确，session
    响应    ： 返回JSON数据 0 成功。 400 失败

    POST        /login/
步骤：
    1. 接收数据
    2. 验证数据
    3. 验证用户名和密码是否正确
    4. session
    5. 判断是否记住登录
    6. 返回响应

"""


class LoginView(View):
    def post(self, request):
        # 接收数据
        data = json.loads((request.body.decode()))
        username = data.get('username')
        password = data.get('password')
        remembered = data.get('remembered')
        # 验证数据
        if not all([username, password]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})
        # 确定我们根据手机号查询还是 根据用户名查询
        if re.match('1[3-9]\d{9}', username):
            # USERNAME_FIELD 我们可以根据 修改User.USERNAME_FIELD字段
            # 来影响authenticate的查询
            User.USERNAME_FIELD = 'mobile'
        else:
            User.USERNAME_FIELD = 'username'

        # 验证用户名和密码是否正确
        # from models import models
        # 方式1: 可以通过模型根据用户名查询
        # user = User.objects.get(username=username)
        # 方式2: 系统提供的方法authenticate
        # 如果用户名密码正确,返回user
        # 如果用户名密码错误,则返回None
        from django.contrib.auth import authenticate
        user = authenticate(username=username, password=password)
        if user is None:
            return JsonResponse({'code': 400, 'errmsg': '账号密码错误'})
        # session
        from django.contrib.auth import login
        login(request, user)
        # 判断是否记住登录
        if remembered:
            # 记住登录
            # 设置session时间

            request.session.set_expiry(None)
        else:
            # 不记住登录
            request.session.set_expiry(0)

        # 返回响应
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        if re.match('1[3-9]\d{9}', username):
            response.set_cookie('username', User.objects.get(mobile=username).username)
        else:
            response.set_cookie('username', username)
        return response


"""
前端：
    当用户点击退出按钮的时候，前端发送一个axios get请求

后端：
    请求
    业务逻辑        退出
    响应      返回JSON数据
"""


class LogoutView(View):

    def delete(self, request):
        # 1. 删除session信息
        logout(request)

        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        # 2. 删除cookie信息，为什么要是删除呢？ 因为前端是根据cookie信息来判断用户是否登录的
        response.delete_cookie('username')

        return response


from utils.views import LoginRequiredJSONMixin


class CenterView(LoginRequiredJSONMixin, View):

    def get(self, request):
        info_data = {
            'username': request.user.username,
            'email': request.user.email,
            'mobile': request.user.mobile,
            'email_active': request.user.email_active,
        }

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'info_data': info_data})


class SaveEmailView(LoginRequiredJSONMixin, View):
    def put(self, request):
        data = json.loads(request.body.decode())
        email = data.get('email')
        user = request.user
        from django.core.mail import send_mail
        subject = "笛菲商城激活邮件"
        from_email = "笛菲商城<17313647075@163.com>"
        recipient_list = [email, '17313647075@163.com']
        # 对<a>标签的连接数据进行加密处理
        # user_id=1
        from apps.users.utils import generic_emai_verif_token
        token = generic_emai_verif_token(user.id)
        # 组织我们的激活邮件
        verify_url = "http://www.difei.site:8080/success_verify_email.html?token=%s" % token
        message = ""
        html_message = '<p>尊敬的用户您好！</p>' \
                       '<p>感谢您使用美多商城。</p>' \
                       '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
                       '<p><a href="%s">%s<a></p>' % (email, verify_url, verify_url)
        # from celery_tasks.email.tasks import celery_send_email
        # celery_send_email.delay(subject, message, from_email, recipient_list, html_message)
        send_mail(
            subject=subject,
            message=message,
            from_email=from_email,
            recipient_list=recipient_list,
            html_message=html_message
        )
        user.email = email
        user.save()

        return JsonResponse({'code': 0, 'errmsg': 'ok'})


"""
需求：激活用户的邮件
前端：
    用户点击激活连接，激活连接携带了token
后端：
    请求：     接受请求，获取参数，验证参数
    业务逻辑：  user_id,根据用户id查询数据，修改数据
    响应：     返回json
    路由：     PUT /emails/verification/ token不在body
    步骤：     1.接受请求
              2.获取参数
              3.验证参数
              4.获取user_id
              5.根据用户id查询数据
              6.修改数据
              7，返回json
"""


class EmailVerifyView(View):
    def put(self, request):
        # 1. 接受请求
        params = request.GET
        # 2.获取参数
        token = params.get('token')
        # 3.验证参数
        if token is None:
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})
        # 4.获取user_id
        from apps.users.utils import check_verify_token
        user_id = check_verify_token(token)
        if user_id is None:
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})
        # 5.根据用户id查询数据
        user = User.objects.get(id=user_id)
        # 6. 修改数据
        user.email_active = True
        user.save()
        # 7，返回json
        return JsonResponse({'code': 0, 'errmsg': 'ok'})
